package com.ncmmall.api.apis.mall.live;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.PhoneUtil;
import com.ncmmall.api.apis.service.Result;
import com.ncmmall.api.params.LiveGoodsDTO;
import com.ncmmall.api.params.LiveLoginDTO;
import com.ncmmall.api.security.Securitys;
import com.ncmmall.application.business.live.LiveApplication;
import com.ncmmall.application.business.live.LiveSettingApplication;
import com.ncmmall.application.business.live.LiveWithdrawApplication;
import com.ncmmall.application.business.member.MemberApplication;
import com.ncmmall.cache.redis.RedisService;
import com.feijin.commons.lang.Requires;
import com.feijin.commons.securitys.MD5HashUtils;
import com.ncmmall.domain.business.bankcard.BankCard;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.live.LiveAccountRemove;
import com.ncmmall.domain.business.live.LiveChannel;
import com.ncmmall.domain.business.live.LiveCheck;
import com.ncmmall.domain.business.live.LiveFeedback;
import com.ncmmall.domain.business.live.LiveGoods;
import com.ncmmall.domain.business.live.LiveGoodsAnchor;
import com.ncmmall.domain.business.live.LiveSession;
import com.ncmmall.domain.business.live.LiveSessionGoods;
import com.ncmmall.domain.business.live.LiveSetting;
import com.ncmmall.domain.business.live.LiveWithdraw;
import com.ncmmall.domain.business.live.QLiveSessionGoods;
import com.ncmmall.domain.security.role.RoleType;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 直播接口
 *
 * @author Samuel
 * @date 2020-09-02 15:18
 */
@RestController
@RequestMapping("/live")
@Slf4j
@RequiredArgsConstructor
public class LiveApi {

    private final QueryChannelService queryChannelService;
    private final LiveApplication liveApplication;
    private final MemberApplication memberApplication;
    private final LiveSettingApplication liveSettingApplication;
    private final RedisService redisService;
    private final LiveWithdrawApplication liveWithdrawApplication;

    @Value("${store.domain}")
    private String storeDomain;

    /**
     * 主播申请(用户已注册)
     */
    @PostMapping("/apply")
    public Result apply(HttpServletRequest request, @RequestBody LiveCheck params) {
        Result result = new Result();
        try {
            Requires.hasLength(params.getMobileCode(), "请输入4位短信验证码");

            WebUser user = Securitys.user(request);
            Requires.hasLength(user.getMobile(), "当前用户未绑定手机号码");

            String mobileCode = redisService.get("msm-" + user.getMobile());
            Requires.isTrue(params.getMobileCode().equals(mobileCode), "手机验证码不正确");

            params.setUser(user);

            liveApplication.apply(params);
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[主播申请异常]", e);
            return result.fail().setMsg("申请异常");
        }
    }

    /**
     * 查询当前用户是否已申请主播
     */
    @GetMapping("/apply/query")
    public Result applyQuery(HttpServletRequest request) {
        Result result = new Result();
        try {
            int status;
            WebUser user = Securitys.user(request);
            if (user.getLiveType() > 0) {
                status = user.getLiveType();
            } else {
                LiveCheck check = queryChannelService.queryOneEntity("select * from live_check where user_id = :uid order by id desc limit 1",
                        ImmutableMap.of("uid", user.getId()), LiveCheck.class);
                if (check == null) {
                    status = 3;
                } else if (check.getCheckStatus() == 1) {
                    status = 4;
                } else {
                    status = 5;
                }
            }
            return result.ok().inject(ImmutableMap.of("status", status));
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[查询主播申请状态异常]", e);
            return result.fail().setMsg("查询异常");
        }
    }

    /**
     * 创建助理账号
     */
    @PostMapping("/createAssistant")
    public Result createAssistant(HttpServletRequest request, @RequestBody LiveLoginDTO params) {
        Result result = new Result();
        try {

            Requires.hasLength(params.getMobile(), "请输入账号");
            Requires.isTrue(PhoneUtil.isMobile(params.getMobile()), "手机号码格式不正确");
            Requires.hasLength(params.getPassword(), "请输入密码");
            Requires.hasLength(params.getRealName(), "请输入姓名");
            Requires.hasLength(params.getAvatar(), "请上传头像");

            Requires.isTrue(!memberApplication.existByUsername(params.getMobile(), RoleType.ANCHOR), "用户名已存在");
            Requires.isTrue(!memberApplication.existByMobile(params.getMobile(), RoleType.ANCHOR), "手机号码已存在");

            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            WebUser assistant = new WebUser();
            assistant.setAnchor(anchor);
            assistant.setUsername(params.getMobile());
            assistant.setPassword(params.getPassword());
            assistant.setRealName(params.getRealName());
            assistant.setMobile(params.getMobile());
            assistant.setAvatar(params.getAvatar());
            memberApplication.registerAssistant(assistant);
            return result.ok();
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[创建助理账号异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 助理登录
     */
    @PostMapping("/login")
    public Result login(HttpServletRequest request, @RequestBody LiveLoginDTO params) {
        Result result = new Result();
        try {

            Requires.hasLength(params.getUsername(), "请输入账号");
            Requires.hasLength(params.getPassword(), "请输入密码");

            WebUser user = memberApplication.findAssistantByUsername(params.getUsername());
            if (user == null) {
                return result.fail().setMsg("账号不存在");
            }

            if (!user.isAccountNonLocked()) {
                return result.fail().setMsg("该账号已被禁用，请联系平台管理员");
            }

            String passwordAsMd5 = MD5HashUtils.asMD5(params.getPassword(), user.getUsername());
            if (!user.getPassword().equals(passwordAsMd5)) {
                return result.fail().setMsg("账号密码错误");
            }

            user = memberApplication.login(user, Securitys.ipAddress(request));
            return result.ok().inject(ImmutableMap.of("token", user.getAccessToken(), "refreshToken", user.getRefreshToken()));

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("登录异常", e);
            return result.fail().setMsg("网络连接异常");
        }
    }

    /**
     * 找回密码
     */
    @PostMapping("/forgetPassword")
    public Result forgetPassword(@RequestBody LiveLoginDTO params) {
        Result result = new Result();
        try {

            Requires.hasLength(params.getMobile(), "请输入手机号");
            Requires.hasLength(params.getMobileCode(), "请输入手机号验证码");
            Requires.hasLength(params.getPassword(), "请输入新密码");

            String mobileCode = redisService.get("msm-" + params.getMobile());
            Requires.isTrue(params.getMobileCode().equals(mobileCode), "手机验证码不正确");

            WebUser anchor = queryChannelService.findOne(QWebUser.webUser.mobile.eq(params.getMobile()), WebUser.class);
            Requires.notNull(anchor, "账号不存在");

            memberApplication.modifyPassword(anchor, params.getPassword());
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[找回密码异常]", e);
            return result.fail().setMsg("网络连接异常");
        }
    }

    /**
     * 主播详情
     */
    @GetMapping("/anchor/detail")
    public Result anchorDetail(HttpServletRequest request) {

        Result result = new Result();
        try {
            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            Map<String, Object> data = new TreeMap<>();
            data.put("liveID", anchor.getLiveID());
            data.put("liveName", anchor.getLiveName());
            data.put("liveIntroduce", anchor.getLiveIntroduce());
            data.put("liveImage", storeDomain + "/uploads/" + anchor.getLiveImage());
            data.put("liveImageStr", anchor.getLiveImage());
            data.put("realName", anchor.getRealName());
            data.put("idCardNo", anchor.getLiveIdCardNo());
            data.put("idCardFront", storeDomain + "/uploads/" + anchor.getLiveIdCardFront());
            data.put("idCardFrontStr", anchor.getLiveIdCardFront());
            data.put("idCardReverse", storeDomain + "/uploads/" + anchor.getLiveIdCardReverse());
            data.put("idCardReverseStr", anchor.getLiveIdCardReverse());
            data.put("liveStatus", anchor.isLiveStatus());
            data.put("liveSessionId", anchor.getLiveSession() == null ? null : anchor.getLiveSession().getId());

            return result.ok().inject(data);

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[主播详情异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 获取直播间开通协议
     */
    @GetMapping("/getOpenProtocol")
    public Result getOpenProtocol() {
        Result result = new Result();
        try {
            LiveSetting liveSetting = liveSettingApplication.findLastSetting();
            String content = liveSetting == null ? "" : Strings.nullToEmpty(liveSetting.getOpenProtocol());
            return result.ok().inject(ImmutableMap.of("content", content));
        } catch (Exception e) {
            log.error("[获取直播间开通协议异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 获取直播间关于我们
     */
    @GetMapping("/aboutUs")
    public Result aboutUs() {
        Result result = new Result();
        try {
            LiveSetting liveSetting = liveSettingApplication.findLastSetting();
            String content = liveSetting == null ? "" : Strings.nullToEmpty(liveSetting.getAboutUs());
            return result.ok().inject(ImmutableMap.of("content", content));
        } catch (Exception e) {
            log.error("[获取直播关于我们异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 设置修改直播间信息
     */
    @PostMapping("/modifyLiveInfo")
    public Result modifyLiveInfo(HttpServletRequest request, @RequestBody LiveLoginDTO params) {
        Result result = new Result();
        try {

            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            if (StringUtils.isNotBlank(params.getNickname()) && !params.getNickname().equals(anchor.getNickname())) {
                if (anchor.getModifyNicknameTime() != null && System.currentTimeMillis() - anchor.getModifyNicknameTime().getTime() < 15 * 24 * 3600 * 1000) {
                    return result.fail().setMsg("姓名15天内之内修改一次");
                }
                anchor.setNickname(params.getNickname());
                anchor.setModifyNicknameTime(new Timestamp(System.currentTimeMillis()));
            }

            if (StringUtils.isNotBlank(params.getAvatar()) && (StringUtils.isBlank(anchor.getAvatar()) || !anchor.getAvatar().equals(params.getAvatar()))) {
                anchor.setAvatar(params.getAvatar());
            }

            if (StringUtils.isNotBlank(params.getImage()) && (StringUtils.isBlank(anchor.getLiveImage()) || !anchor.getLiveImage().equals(params.getImage()))) {
                anchor.setLiveImage(params.getImage());
            }

            if (StringUtils.isNotBlank(params.getName()) && (StringUtils.isBlank(anchor.getLiveName()) || !anchor.getLiveName().equals(params.getName()))) {
                anchor.setLiveName(params.getName());
            }

            if (StringUtils.isNotBlank(params.getIntroduce()) && (StringUtils.isBlank(anchor.getLiveIntroduce()) || !anchor.getLiveIntroduce().equals(params.getIntroduce()))) {
                anchor.setLiveIntroduce(params.getIntroduce());
            }

            liveApplication.save(anchor);
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[设置修改直播间信息异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 直播助理账号列表
     */
    @GetMapping("/assistantList")
    public Result assistantList(HttpServletRequest request) {
        Result result = new Result();
        try {

            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            List<Map<String, Object>> assistants = queryChannelService.selectAllMap("select avatar, realName, createTime from security_web_user where liveType = 2 and anchor_id = :aid order by createTime desc", ImmutableMap.of("aid", anchor.getId()));
            for (Map<String, Object> assistant : assistants) {
                String avatar = MapUtil.getStr(assistant, "avatar");
                if (StringUtils.isNotBlank(avatar)) {
                    assistant.put("avatar", storeDomain + "/avatar/" + avatar);
                }
            }
            return result.ok().inject(assistants);

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[直播助理账号列表异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 代播商品池商品列表
     *
     * @param type 1、热卖商品（排序值）
     *             2、佣金最高
     *             3、新品商品
     */
    @GetMapping("/goodsList")
    public Result goodsList(HttpServletRequest request, @RequestParam(defaultValue = "1") int type,
                            QueryPageRequest pageRequest) {

        Result result = new Result();
        try {

            Requires.isTrue(type >= 1 && type <= 3, "参数不正确");

            WebUser anchor = Securitys.user(request);
            if (anchor.getLiveType() != 1 && anchor.getLiveType() != 2) {
                return result.fail().setMsg("主播不存在");
            }
            if (anchor.getLiveType() == 2) {
                Requires.notNull(anchor.getAnchor(), "主播不存在");
                anchor = anchor.getAnchor();
            }
            LiveApplication.requireUserIsAnchor(anchor);

            String sql = "select g from LiveGoodsAnchor g where g.anchor.id = :aid and g.liveGoods.status = 1 and g.liveGoods.goods.status = 3 ";

            if (type == 1) {
                sql += " order by g.liveGoods.rank desc";
            } else if (type == 2) {
                sql += " order by g.liveGoods.guaranteeScale desc";
            } else {
                sql += " order by g.liveGoods.createTime desc";
            }
            QueryPage<LiveGoodsAnchor> page = queryChannelService.findPage(sql, pageRequest.setParams(ImmutableMap.of("aid", anchor.getId())), LiveGoodsAnchor.class);

            List<Map<String, Object>> data = page.getResult().stream().map(lg -> {

                Goods g = lg.getLiveGoods().getGoods();
                return MapUtil.<String, Object>builder()
                        .put("id", lg.getId())
                        .put("goodsId", g.getId())
                        .put("goodsImage", storeDomain + "/uploads/" + g.getDefaultImage())
                        .put("goodsName", g.getName())
                        .put("goodsPirce", g.getDefaultPrice())
                        .put("store", g.getStore())
                        .put("guaranteeScale", NumberUtil.round(lg.getLiveGoods().getGuaranteeScale() * 100, 2))
                        .put("isAdd", queryChannelService.selectCount("select count(*) from live_session_goods where live_goods_anchor_id = :aid and live_session_id is null", ImmutableMap.of("aid", lg.getId())) > 0)
                        .build();

            }).collect(Collectors.toList());
            return result.ok().inject(new QueryPage<>(page.getTotalCount(), data, pageRequest.getPageNo(), pageRequest.getPageSize()));
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取代播商品池列表异常]", e);
            return result.fail().setMsg("网络连接异常");
        }
    }

    /**
     * 代播商品池商品详情
     *
     * @param id 代播商品ID
     */
    @GetMapping("/goodsDetail")
    public Result goodsDetail(HttpServletRequest request, Long id) {
        Result result = new Result();
        try {
            Requires.notNull(id, "代播商品id不能为空");

            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            LiveGoodsAnchor goodsAnchor = queryChannelService.findOne(LiveGoodsAnchor.class, id);
            Requires.isTrue(goodsAnchor != null && goodsAnchor.getAnchor().getId() == anchor.getId(), "代播商品不存在");

            LiveGoods liveGoods = goodsAnchor.getLiveGoods();
            Goods goods = goodsAnchor.getGoods();

            Map<String, Object> data = new TreeMap<>();
            data.put("goodsName", goods.getName());
            data.put("goodsPirce", goods.getDefaultPrice());
            data.put("store", goods.getStore());
            data.put("guaranteeScale", NumberUtil.round(liveGoods.getGuaranteeScale() * 100, 2));
            data.put("goodsParams", goods.getParamses());
            data.put("content", goods.getContent());
            data.put("goodsImage", storeDomain + "/uploads/" + goods.getDefaultImage());
            data.put("commission", NumberUtil.round(goods.getDefaultPrice() * liveGoods.getGuaranteeScale(), 2));

            return result.ok().inject(data);
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取代播商品详情异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 代播商品池商品添加到我的代播商品
     */
    @PostMapping("/addGoodsManager")
    public Result addGoodsManager(HttpServletRequest request, @RequestBody LiveGoodsDTO params) {
        Result result = new Result();
        try {
            Requires.hasLength(params.getIds(), "请选择商品");

            WebUser anchor = Securitys.user(request);
            if (anchor.getLiveType() != 1 && anchor.getLiveType() != 2) {
                return result.fail().setMsg("主播不存在");
            }
            if (anchor.getLiveType() == 2) {
                Requires.notNull(anchor.getAnchor(), "主播不存在");
                anchor = anchor.getAnchor();
            }
            LiveApplication.requireUserIsAnchor(anchor);

            liveApplication.addGoodsManager(anchor, params.getIds());
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[添加代播商品池到我的代播商品异常]", e);
            return result.fail().setMsg("添加异常");
        }
    }


    /**
     * 我的代播商品列表
     */
    @GetMapping("/liveSessionGoodsList")
    public Result liveSessionGoodsList(HttpServletRequest request) {

        Result result = new Result();
        try {

            WebUser anchor = Securitys.user(request);
            if (anchor.getLiveType() != 1 && anchor.getLiveType() != 2) {
                return result.fail().setMsg("主播不存在");
            }
            if (anchor.getLiveType() == 2) {
                Requires.notNull(anchor.getAnchor(), "主播不存在");
                anchor = anchor.getAnchor();
            }
            LiveApplication.requireUserIsAnchor(anchor);

            List<LiveSessionGoods> sessionGoodsList;
            if (anchor.isLiveStatus()) {
                //直播当中
                LiveSession liveSession = anchor.getLiveSession();
                sessionGoodsList = queryChannelService.findAll(QLiveSessionGoods.liveSessionGoods.liveSession.id.eq(liveSession.getId()), LiveSessionGoods.class);
            } else {
                //未开播
                sessionGoodsList = queryChannelService.findAll(QLiveSessionGoods.liveSessionGoods.anchor.id.eq(anchor.getId()).and(QLiveSessionGoods.liveSessionGoods.liveSession.isNull()), LiveSessionGoods.class);
            }

            List<Map<String, Object>> list = sessionGoodsList.stream().map(sessionGoods -> {
                Goods goods = sessionGoods.getGoods();
                Map<String, Object> map = new TreeMap<>();
                map.put("id", sessionGoods.getId());
                map.put("goodsId", goods.getId());
                map.put("goodsImage", storeDomain + "/uploads/" + goods.getDefaultImage());
                map.put("goodsName", goods.getName());
                map.put("goodsPirce", goods.getDefaultPrice());
                map.put("store", goods.getStore());
                map.put("guaranteeScale", NumberUtil.round(sessionGoods.getLiveGoodsAnchor().getLiveGoods().getGuaranteeScale() * 100, 2));
                return map;
            }).collect(Collectors.toList());

            return result.ok().inject(ImmutableMap.of("list", list));

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取我的代播商品列表异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 我的代播商品详情
     *
     * @param id 代播商品ID
     */
    @GetMapping("/liveSessionGoodsDetail")
    public Result liveRoomGoodsDetail(HttpServletRequest request, @RequestParam Long id) {

        Result result = new Result();
        try {

            Requires.notNull(id, "代播商品id不能为空");

            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            LiveSessionGoods sessionGoods = queryChannelService.findOne(LiveSessionGoods.class, id);
            Requires.isTrue(sessionGoods != null && sessionGoods.getAnchor().getId() == anchor.getId(), "商品不存在");

            Goods goods = sessionGoods.getGoods();
            Map<String, Object> data = new TreeMap<>();

            data.put("goodsName", goods.getName());
            data.put("goodsPirce", goods.getDefaultPrice());
            data.put("store", goods.getStore());
            double scale = sessionGoods.getLiveGoodsAnchor().getLiveGoods().getGuaranteeScale();
            data.put("guaranteeScale", NumberUtil.round(scale * 100, 2));
            data.put("goodsParams", goods.getParamses());
            data.put("content", goods.getContent());
            data.put("goodsImage", storeDomain + "/uploads/" + goods.getDefaultImage());
            data.put("commission", NumberUtil.round(goods.getDefaultPrice() * scale, 2));

            data.put("commonRedPacketPrice", sessionGoods.getCommonRedPacketPrice());
            data.put("commonRedPacketSec", sessionGoods.getCommonRedPacketSec());
            data.put("commonRedPacketHour", sessionGoods.getCommonRedPacketHour());
            data.put("vieRedPacketPrice", sessionGoods.getVieRedPacketPrice());
            data.put("vieRedPacketSec", sessionGoods.getVieRedPacketSec());
            data.put("vieRedPacketHour", sessionGoods.getVieRedPacketHour());

            return result.ok().inject(data);

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取我的代播商品详情异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }


    /**
     * 商品详情—设置红包
     */
    @PostMapping("/settingRedPacket")
    public Result settingRedPacket(HttpServletRequest request, @RequestBody LiveGoodsDTO params) {

        Result result = new Result();
        try {

            Requires.isTrue(params.getRedPacketType() == 1 || params.getRedPacketType() == 2, "红包类型不正确");
            Requires.isTrue(params.getId() > 0, "代播商品ID不存在");

            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            LiveSessionGoods sessionGoods = queryChannelService.findOne(LiveSessionGoods.class, params.getId());
            Requires.isTrue(sessionGoods != null && sessionGoods.getAnchor().getId() == anchor.getId(), "代播商品不存在");
            Requires.isTrue(sessionGoods.getLiveSession() == null, "商品已开始直播，无法设置红包");

            //单笔订单佣金
            double price = NumberUtil.round(sessionGoods.getLiveGoodsAnchor().getLiveGoods().getGuaranteeScale() * sessionGoods.getGoods().getDefaultPrice(), 2).doubleValue();

            if (params.getRedPacketType() == 1) {
                Requires.isTrue(price >= params.getCommonRedPacketPrice(), "您输入的金额超过佣金，请重新输入");
                Requires.isTrue(params.getCommonRedPacketPrice() > 0, "红金金额必须大于0");
                Requires.isTrue(params.getCommonRedPacketSec() > 0, "红包发放时间必须大于0");
                Requires.isTrue(params.getCommonRedPacketHour() > 0, "红包有效时间必须大于0");

                sessionGoods.setCommonRedPacketPrice(params.getCommonRedPacketPrice());
                sessionGoods.setCommonRedPacketSec(params.getCommonRedPacketSec());
                sessionGoods.setCommonRedPacketHour(params.getCommonRedPacketHour());

            } else {
                Requires.isTrue(price >= params.getVieRedPacketPrice(), "您输入的金额超过佣金，请重新输入");
                Requires.isTrue(params.getVieRedPacketPrice() > 0, "红金金额必须大于0");
                Requires.isTrue(params.getVieRedPacketSec() > 0, "红包发放时间必须大于0");
                Requires.isTrue(params.getVieRedPacketHour() > 0, "红包有效时间必须大于0");

                sessionGoods.setVieRedPacketPrice(params.getVieRedPacketPrice());
                sessionGoods.setVieRedPacketSec(params.getVieRedPacketSec());
                sessionGoods.setVieRedPacketHour(params.getVieRedPacketHour());
            }

            liveApplication.saveSessionGoods(sessionGoods);
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[商品详情—设置红包异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    /**
     * 直播分类列表
     */
    @GetMapping("/channel/list")
    public Result channelList() {
        Result result = new Result();
        try {
            List<LiveChannel> liveChannels = queryChannelService.findAll("from LiveChannel l", LiveChannel.class);
            List<Map<String, Object>> list = liveChannels.stream().map(c -> {
                Map<String, Object> map = new HashMap<>();
                map.put("id", c.getId());
                map.put("name", c.getName());
                return map;
            }).collect(Collectors.toList());
            return result.ok().inject(ImmutableMap.of("list", list));
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[开始直播异常]", e);
            return result.fail().setMsg("开始直播异常");
        }
    }

    /**
     * 游客访问直播列表
     *
     * @param channelId 直播分类id 0表示精选 -1表示我关注的 其他表示直播分类id
     * @param keyword   关键字
     */
    @GetMapping("/list")
    public Result list(HttpServletRequest request, QueryPageRequest pageRequest, Long channelId, String keyword) {

        Result result = new Result();
        try {

            if (StringUtils.isBlank(keyword)) {
                Requires.notNull(channelId, "请选择分类");
            }
            if (channelId == null) {
                Requires.hasLength(keyword, "请输入搜索关键字");
            }

            QueryPage<LiveSession> page;
            Map<String, Object> params = new HashMap<>();

            if (channelId != null && channelId == -1) {
                //我关注的
                Requires.isTrue(Securitys.isLogin(request), "请登录");
                String sql = "select * from live_session s left join live_fans lf on s.anchor_id = lf.anchor_id where lf.fans_id = :uid and s.end_time is null order by s.look_number desc";
                params.put("uid", Securitys.user(request));
                page = queryChannelService.queryPageEntity(sql, pageRequest.setParams(params), LiveSession.class);
            } else {
                //其他类型直播
                String hql = buildListHql(params, channelId, keyword);
                page = queryChannelService.findPage(hql, pageRequest.setParams(params), LiveSession.class);
            }

            List<Map<String, Object>> list = page.getResult().stream()
                    .map(s -> {
                        Map<String, Object> session = new HashMap<>();
                        session.put("lookNumber", s.getLookNumber());
                        session.put("name", s.getName());
                        session.put("nickname", s.getAnchor().getNickname());
                        session.put("anchorId", s.getAnchor().getId());
                        session.put("likeNumber", s.getLikeNumber());
                        session.put("image", storeDomain + "/uploads/" + s.getImage());
                        session.put("id", s.getId());
                        session.put("liveID", s.getAnchor().getLiveID());
                        return session;
                    })
                    .collect(Collectors.toList());

            return result.ok().inject(ImmutableMap.of("page", new QueryPage<>(page.getTotalCount(), list, pageRequest.getPageNo(), pageRequest.getPageSize())));

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取直播间列表异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    private String buildListHql(Map<String, Object> map, Long channelId, String keyword) {
        StringBuilder hql = new StringBuilder("from LiveSession s where s.endTime = null ");
        if (channelId != null) {
            if (channelId == 0) {
                hql.append(" and s.choiceness = true");
            } else {
                hql.append(" and s.liveChannel.id = :cid");
                map.put("cid", channelId);
            }
        }
        if (StringUtils.isNotBlank(keyword)) {
            hql.append(" and (s.name like :name or s.anchor.nickname like :name)");
            map.put("name", "%" + keyword + "%");
        }
        hql.append(" order by s.lookNumber desc");
        return hql.toString();
    }

    /**
     * 注销主播账号
     */
    @DeleteMapping("/closeAccount")
    public Result closeAccount(HttpServletRequest request, @RequestBody LiveAccountRemove accountRemove) {
        Result result = new Result();
        try {
            Requires.hasLength(accountRemove.getReason(), "请输入注销理由");
            WebUser anchor = Securitys.user(request);
            LiveApplication.requireUserIsAnchor(anchor);

            accountRemove.setUser(anchor);
            liveApplication.closeAccount(accountRemove);
            return result.ok();
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[主播注销异常]", e);
            return result.fail().setMsg("注销异常");
        }
    }

    /**
     * 直播反馈
     */
    @PostMapping("/feeback")
    public Result feeback(HttpServletRequest request, @RequestBody LiveFeedback feedback) {
        Result result = new Result();
        try {
            Requires.hasLength(feedback.getContent(), "请输入问题");
            WebUser user = Securitys.user(request);
            feedback.setUser(user);
            liveApplication.feedback(feedback);
            return result.ok();
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[直播反馈异常]", e);
            return result.fail().setMsg("反馈异常");
        }
    }

    /**
     * 直播申请提现
     */
    @PostMapping(value = "/withdraw")
    public Result withdraw(HttpServletRequest request, @RequestBody LiveWithdraw params) {
        Result result = new Result();
        try {

            WebUser user = Securitys.user(request);
            Requires.isTrue(user.getLiveType() == 1, "当前用户不是主播");

            final double money = params.getMoney();
            Requires.isTrue(user.getLiveBalance() >= money, "输入金额超过零钱余额");

            Requires.notNull(params.getBankCardId(), "银行卡不能为空");
            BankCard card = queryChannelService.findOne(BankCard.class, params.getBankCardId());
            Requires.notNull(card, "银行卡不存在");
            Requires.isTrue(card.getMember().getId() == user.getId(), "银行卡不正确");

            LiveSetting setting = liveSettingApplication.findLastSetting();
            if (setting != null) {
                if (setting.getMinPrice() != null) {
                    Requires.isTrue(money >= setting.getMinPrice(), "提现最小金额" + setting.getMinPrice());
                }
                if (setting.getMaxPrice() != null) {
                    Requires.isTrue(money <= setting.getMaxPrice(), "提现最大金额" + setting.getMaxPrice());
                }
                if (setting.getWithdrawNumPerDay() != null) {
                    int count = queryChannelService.selectCount("select count(*) from business_live_withdraw where user_id = :did and date(createTime) = date(now())", ImmutableMap.of("did", user.getId()));
                    Requires.isTrue(count < setting.getWithdrawNumPerDay(), "提现已达当天最大次数");
                }
                if (setting.getWithdrawNumPerMonth() != null) {
                    int count = queryChannelService.selectCount("select count(*) from business_live_withdraw where user_id = :did and datediff(now(), createTime) <= 30", ImmutableMap.of("did", user.getId()));
                    Requires.isTrue(count < setting.getWithdrawNumPerMonth(), "提现已达当月最大次数");
                }
            }

            LiveWithdraw withdraw = new LiveWithdraw();
            withdraw.setMoney(money);
            withdraw.setUser(user);
            withdraw.setCreateTime(new Timestamp(System.currentTimeMillis()));
            withdraw.setStatus(1);
            withdraw.setPayType(2);
            withdraw.setBankName(card.getBankName());
            withdraw.setBankCardNo(card.getBankCardNo());
            withdraw.setBankProvince(card.getBankProvince());
            withdraw.setBankCity(card.getBankCity());
            withdraw.setBankSubBranch(card.getBankSubBranch());
            withdraw.setBankAccoutName(card.getAccountName());
            liveWithdrawApplication.create(withdraw);
            return result.ok();
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[申请提现异常]", e);
            return result.fail().setMsg("申请异常");
        }
    }

    /**
     * 获取主播余额
     */
    @GetMapping(value = "/balance")
    public Result balance(HttpServletRequest request) {
        Result result = new Result();
        try {
            WebUser user = Securitys.user(request);
            Requires.isTrue(user.getLiveType() == 1, "当前用户不是主播");
            return result.ok().inject(ImmutableMap.of("balance", user.getLiveBalance()));
        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取主播余额异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

}
